﻿using Common.FrontEnd;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common
{
    public interface IToken
    {
        /// <summary>
        /// Returns the predecessor for this token, or null if this token has no predecessors
        /// </summary>
        /// <returns></returns>
        IToken getPredecessor();
        /// <summary>
        /// Returns the frame number for this token. Note that for tokens that are associated with non-emitting states, the
        /// frame number represents the next frame number.  For emitting states, the frame number represents the current
        /// frame number.
        /// </summary>
        /// <returns></returns>
        int getFrameNumber();
        /// <summary>
        /// Sets the feature for this Token.
        /// </summary>
        /// <param name="data"></param>
        void setData(IData data);
        /// <summary>
        /// Returns the feature for this Token.
        /// </summary>
        /// <returns></returns>
        IData getData();

        /// <summary>
        /// Returns the score for the token. The score is a combination of language and acoustic scores
        /// </summary>
        /// <returns></returns>
        float getScore();
        
        /// <summary>
        /// Calculates a score against the given feature. The score can be retrieved 
        /// with get score. The token will keep a reference to the scored feature-vector.
        /// </summary>
        /// <param name="feature">the feature to be scored</param>
        /// <returns>the score for the feature</returns>
        float calculateScore(IData feature);

        float[] calculateComponentScore(IData feature);

        /// <summary>
        /// Normalizes a previously calculated score
        /// </summary>
        /// <param name="maxLogScore">the score to normalize this score with</param>
        /// <returns>the normalized score</returns>
        float normalizeScore(float maxLogScore);

        /// <summary>
        /// Gets the working score. The working score is used to maintain non-final
        /// scores during the search. Some search algorithms such as bushderby use
        /// the working score
        /// </summary>
        /// <returns>the working score (in logMath log base)</returns>
        float getWorkingScore();

        /// <summary>
        /// Sets the working score for this token
        /// </summary>
        /// <param name="logScore">the working score (in logMath log base)</param>
        void setWorkingScore(float logScore);

        /// <summary>
        /// Sets the score for this token
        /// </summary>
        /// <param name="logScore">the new score for the token (in logMath log base)</param>
        void setScore(float logScore);
        /// <summary>
        /// Returns the language score associated with this token
        /// </summary>
        /// <returns></returns>
        float getLanguageScore();

        /// <summary>
        /// Returns the insertion score associated with this token.
        /// Insertion score is the score of the transition between
        /// states. It might be transition score from the acoustic model,
        /// phone insertion score or word insertion probability from
        /// the linguist.

        /// </summary>
        /// <returns></returns>
        float getInsertionScore();
        /// <summary>
        /// Returns the acoustic score for this token (in logMath log base).
        /// Acoustic score is a sum of frame GMM.
        /// </summary>
        /// <returns></returns>
        float getAcousticScore();
        /// <summary>
        /// Returns the SearchState associated with this token
        /// </summary>
        /// <returns></returns>
        ISearchState getSearchState();
        /// <summary>
        /// Determines if this token is associated with an emitting state. An emitting state is a state that can be scored
        /// acoustically.
        /// </summary>
        /// <returns></returns>
        Boolean isEmitting();
        /// <summary>
        /// Determines if this token is associated with a final SentenceHMM state.
        /// </summary>
        /// <returns></returns>
        Boolean isFinal();
        /// <summary>
        /// Determines if this token marks the end of a word
        /// </summary>
        /// <returns></returns>
        Boolean isWord();
        /// <summary>
        /// Retrieves the string representation of this object
        /// </summary>
        /// <returns></returns>

        String ToString();

        /// <summary>
        /// dumps a branch of tokens 
        /// </summary>
        void dumpTokenPath();
        /// <summary>
        /// dumps a branch of tokens
        /// </summary>
        /// <param name="includeHMMStates">if true include all sentence hmm states</param>
        void dumpTokenPath(Boolean includeHMMStates);
        /// <summary>
        /// Returns the string of words leading up to this token.
        /// </summary>
        /// <param name="wantFiller">if true, filler words are added</param>
        /// <param name="wantPronunciations">if true append [ phoneme phoneme ... ] after each word</param>
        /// <returns></returns>
        String getWordPath(Boolean wantFiller, Boolean wantPronunciations);
        /// <summary>
        /// Returns the string of words for this token, with no embedded filler words
        /// </summary>
        /// <returns>the string of words</returns>
        String getWordPathNoFiller();
        /// <summary>
        /// Returns the string of words for this token, with embedded silences
        /// </summary>
        /// <returns>the string of words</returns>
        String getWordPath();
        /// <summary>
        /// Returns the string of words and units for this token, with embedded silences.
        /// </summary>
        /// <returns>the string of words and units</returns>
        String getWordUnitPath();
        /// <summary>
        /// Returns the word of this Token, the search state is a WordSearchState. If the search state is not a
        /// WordSearchState, return null.
        /// </summary>
        /// <returns>the word of this Token, or null if this is not a word token</returns>
        IWord getWord();
        /// <summary>
        /// Returns the location of this Token in the ActiveList. In the HeapActiveList implementation, it is the index of
        /// the Token in the array backing the heap.
        /// </summary>
        /// <returns></returns>
        int getLocation();
        

        /// <summary>
        /// Sets the location of this Token in the ActiveList.
        /// </summary>
        /// <param name="location"></param>
        void setLocation(int location);
        /// <summary>
        /// Determines if this branch is valid
        /// </summary>
        /// <returns>true if the token and its predecessors are valid</returns>
        Boolean validate();

        /// <summary>
        /// Returns the application object
        /// </summary>
        /// <returns></returns>
        Dictionary<String, Object> getTokenProps();
    }
}
